/**
 *
 * \file
 * Identification Beacon functions.
 *
 */

/*
 *
 * Copyright (c) 2010, Jesper Hansen
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *      * Redistributions of source code must retain the above copyright notice, this
 *       list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *     * Neither the name of the copyright holders nor the names of any contributors
 *       may be used to endorse or promote products derived from this software
 *       without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 */

#include "utils/lwiplib.h"
#include "utils/uartstdio.h"
#include "utils/ustdlib.h"


#include <stdint.h>
#include <string.h>

#include "isendir.h"
#include "timeout.h"

static uint32_t beacon_timer = 0;	//!< Beacon frequency in Beats per Minute

static char * beacon_data = "AMXB<-UUID=GC100_000C1E0AF4E1_GlobalCache>"	\
							"<-SDKClass=Utility>" 							\
							"<-Make=GlobalCache>" 							\
							"<-Model=GC-100-06>" 							\
							"<-Revision=1.0.0>" 							\
							"<Config-Name=GC-100>" 							\
							"<Config-URL=http://192.168.1.126>";

//*****************************************************************************
//!
//! Transmit a beacon with our system information.
//! This is used by clients to find our system IP and to verify that we are
//! in fact up and running.
//!
//*****************************************************************************
void beacon(void)
{
	static int initialized = 0;
    static struct udp_pcb *pcb;
    static struct ip_addr ip;
    struct pbuf *p;
    int i;
    char *pstr;
    unsigned long lip;

    //
    // if first time here, perform initialization
    //
    if (!initialized)
    {
    	//
    	// allocate a new pcb for the beacon connection
        pcb = udp_new();
        if (pcb == NULL)
        {
        	ERROR("cannot alloc pcb\n");
			return;
        }

        //
        // get the local IP
        //
        lip = lwIPLocalIPAddrGet();

        //
        // set the local IP as sender address in the multicast packet
        //
    	ip_addr_set(&pcb->multicast_ip,(struct ip_addr*)&lip);

    	//
    	// bind this to a random local port number
    	//
        udp_bind(pcb,(struct ip_addr*)&lip,0);

        //
        // set the multicast IP to use for the beacon
        //
    	IP4_ADDR(&ip,239,255,250,250);

    	//
    	// all initialized, we don't need to come here again
    	//
        initialized = 1;
    }

	printf("\n    -----  beacon  -----\n");

	//
    // Allocate a new pbuf for the beacon data
    //
    p = pbuf_alloc(PBUF_TRANSPORT, strlen(beacon_data)+5, PBUF_RAM);
    if (p == NULL)
    {
    	ERROR("cannot alloc pbuf\n");
		return;
    }

    //
    // point to payload and copy to buffer
    //
    pstr = p->payload;						// get pointer to payload area
    for (i=0;i<strlen(beacon_data)+1;i++)	// copy data
    	pstr[i] = beacon_data[i];

    //
    // multicast beacon data to port 9131
    //
    udp_sendto(pcb, p, &ip, 9131);

    //
    // releast pbuf memory
    //
   	pbuf_free(p);
}


//*****************************************************************************
//!
//! Initialize or reconfigure the beacon transmission frequency.
//!
//*****************************************************************************
void beacon_config(void)
{
	 //
	 // make sure the bpm is at least 1
	 //
	 if (nw_settings.ns_beacon_bpm == 0)
		 nw_settings.ns_beacon_bpm = 1;

  	//
  	// if the beacon was already active, cancel the old timeout
  	//
  	if (beacon_timer > 0)
  		timer_cancel_timeout(beacon_timer);

  	//
  	// set the beacon timeout, causing the FLAG_BEACON flag
  	// to be set on a timeout
  	//
   	beacon_timer = timer_set_timeout(60000/nw_settings.ns_beacon_bpm, NULL, FLAG_BEACON, REPETITIVE);
}


